package com.android.WiFiQualityMeasurement;


import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.telephony.TelephonyManager;
import android.util.Log;
//import android.util.Log;

public class WiFiQualityMeasurementSendInfoService extends Service implements LocationListener{

    private Handler handler = new Handler();


	/* DEBUG ファイル書き出し用 START */
	private String				mStringFilePath;					// ファイル関係
	private File 				mFile;								// ファイル関係
	private FileOutputStream 	mFos;								// ファイル関係
	/* DEBUG ファイル書き出し用 END */
	private TelephonyManager 	mTelephonyManager;					// Telephonyマネージャー
	private String 				mStringLineType;					// 捕捉回線種別
	private WifiManager 		mWifiManager;						// Wifiマネージャー
	private WifiInfo 			mWifiInfo;							// Wifiインフォ
	private ConnectivityManager	mConManager;						// コネクティビティマネージャ
	private NetworkInfo 		mNetInfo;							// ネットワークインフォ
	private String 				mStringThroughput;					// スループット値
	private String 				mStringElectricFieldStrength;		// 電界強度
	private Calendar 			mCalendar;							// カレンダークラス
	private String 				mStringDayTime;						// 年月日時分秒
	private LocationManager		mLocationManager;					// ロケーションマネージャ
	private String				mStringLatitude;					// 緯度
	private String				mStringLongitude;					// 経度
	private String				mStringBssid;						// BSSID
	private String				mStringMacAddress;					// MacAddress
	private String				mStringModel;						// 端末種別
	private String				mStringSsid;						// SSID
	private String				mStringCareerName;					// キャリア名
	private String				mStringPingResult;					// Ping結果

	private WiFiQualityMeasurementPingAsyncTask mTaskPing;

	private WiFiQualityMeasurementPingAsyncTaskPingInfo mPingInfo;

	private final int 			REPEAT_INTERVAL = 5000;						// インターバル5秒
	private final int 			PING_TIMEOUT = 2000;				// Pingタイムアウト

    public static final String ACTION = "WiFiQualityMeasurementSend Service";

	private Runnable runnable = new Runnable() {
		@Override
		public void run() {

			/* 次回処理をセット */
			handler.postDelayed(this, REPEAT_INTERVAL);

			/* 繰り返し処理 */
			// インターバルごとに、Wifi情報を取得する
			getState();

			// Pingの実施
			mTaskPing = new WiFiQualityMeasurementPingAsyncTask(mPingInfo);
			if(mTaskPing != null)
			{
				String str = "";
				mTaskPing.execute(str, null, str);
			}

			// インターバルごとに、ログをサーバにアップロード
			sendLog();


			/* DEBUG ファイル書き出し処理 START */
			//saveState();
			/* DEBUG ファイル書き出し処理 END */
		}
	};

	@Override
	public void onCreate() {
		super.onCreate();

		// インスタンス初期化
		mCalendar = Calendar.getInstance();
		mStringFilePath = Environment.getExternalStorageDirectory() + "/" +
							Integer.toString(mCalendar.get(Calendar.YEAR)) +
							Integer.toString(mCalendar.get(Calendar.MONTH)+1) +
							Integer.toString(mCalendar.get(Calendar.DAY_OF_MONTH)) +
							Integer.toString(mCalendar.get(Calendar.HOUR_OF_DAY)) +
							Integer.toString(mCalendar.get(Calendar.MINUTE)) +
							Integer.toString(mCalendar.get(Calendar.SECOND)) +
							Integer.toString(mCalendar.get(Calendar.MILLISECOND)) +
							".txt";

		mStringLatitude = "";	// 緯度
		mStringLongitude = "";	// 経度

		///* DEBUG ファイル書き出し用初期処理 START */
		//mFile = new File(mStringFilePath);
		//if(mFile != null)
		//{
		//	mFile.getParentFile().mkdir();
		//}
		///* DEBUG ファイル書き出し用初期処理 END */

		mPingInfo = new WiFiQualityMeasurementPingAsyncTaskPingInfo();

		mPingInfo.setTimeout(PING_TIMEOUT);

	}

	@Override
	public void onStart(Intent intent, int startId) {
		super.onStart(intent, startId);

		// GPS開始
		mLocationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);

		if(mLocationManager != null)
		{
			mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, // プロバイダ
													0, // 通知のための最小時間間隔
													0, // 通知のための最小距離間隔
													this); // 位置情報リスナー
    	}

		/* 初回実行 */
		handler.postDelayed(runnable, 0);
	}

	@Override
	public void onDestroy() {

		if(mLocationManager != null)
		{
			/* GPS利用終了 */
			mLocationManager.removeUpdates(this);
		}
		handler.removeCallbacks(runnable);
		runnable = null;

		super.onDestroy();

	}

	@Override
	public IBinder onBind(Intent intent) {
		// TODO 自動生成されたメソッド・スタブ
		return null;
	}

	private void getState(){
		/* TelephonyManagerの取得 */
		mTelephonyManager = ((TelephonyManager) getSystemService(TELEPHONY_SERVICE));

		/* WifiManagerの取得 */
		mWifiManager = (WifiManager) getSystemService(WIFI_SERVICE);

		/* WifiManagerの取得判定 */
		if(mWifiManager != null)
		{
			/* WifiManager取得可の場合 */
			/* Wifi状態の取得 */
			int wifiState = mWifiManager.getWifiState();
			switch (wifiState) {
			case WifiManager.WIFI_STATE_ENABLED:
				/* Wifiの状態が有効の場合 */
				break;
			case WifiManager.WIFI_STATE_DISABLING:
			case WifiManager.WIFI_STATE_DISABLED:
			case WifiManager.WIFI_STATE_UNKNOWN:
			case WifiManager.WIFI_STATE_ENABLING:
				/* Wifiの状態が有効以外の場合 */
				mStringThroughput = "";
				mStringElectricFieldStrength = "";
				mStringBssid = "";
				mStringMacAddress = "";
				mStringSsid = "";
				break;
			}

			/* WifiInfoを取得 */
			mWifiInfo = mWifiManager.getConnectionInfo();
		}
		else
		{
			/* WifiManager取得不可の場合 */

			/* WifiInfoの参照をクリア */
			mWifiInfo = null;
			mStringThroughput = "";
			mStringElectricFieldStrength = "";
			mStringBssid = "";
			mStringMacAddress = "";
			mStringSsid = "";
		}

		mCalendar = Calendar.getInstance();

		/* ConnectivityManagerの取得 */
		mConManager = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);

		/* ConnectivityManagerの取得判定 */
		if(mConManager != null)
		{
			/* ConnectivityManager取得可の場合 */
			/* NetworkInfoを取得 */
			mNetInfo = mConManager.getActiveNetworkInfo();
		} else {
			/* ConnectivityManager取得不可の場合 */
			/* NetworkInfoの参照をクリア */
			mNetInfo = null;
		}

		/* NetworkInfoの取得判定 */
		if(mNetInfo != null)
		{
			/* NetworkInfo取得可の場合 */

			/* 回線種別判定 */
			if(mNetInfo.getType() == ConnectivityManager.TYPE_WIFI)
			{
				/* 回線種別にWiFiの場合 */

				/* 回線種別にWiFiを設定 */
				mStringLineType = "WiFi";


				/* WifiInfoの取得判定 */
				if(mWifiInfo != null)
				{
					/* WifiInfo取得可の場合 */

					/* WiFi情報の設定 */
					mStringThroughput = Integer.toString(mWifiInfo.getLinkSpeed());
					mStringElectricFieldStrength = Integer.toString(mWifiInfo.getRssi());
					mStringBssid = mWifiInfo.getBSSID();
					mStringMacAddress = mWifiInfo.getMacAddress();
					mStringSsid = mWifiInfo.getSSID();
				}else{
					/* WifiInfo取得可の場合 */

					/* WiFi情報のクリア */
					mStringThroughput = "";
					mStringElectricFieldStrength = "";
					mStringBssid = "";
					mStringMacAddress = "";
					mStringSsid = "";
				}

				/* TelephonyManagerの取得判定 */
				if(mTelephonyManager != null)
				{
					/* キャリア名の設定 */
					mStringCareerName = mTelephonyManager.getNetworkOperatorName();
				}
				else
				{
					/* キャリア名のクリア */
					mStringCareerName = "";
				}
			}
			/* 電話回線の場合 */
			else if(mNetInfo.getType() == ConnectivityManager.TYPE_MOBILE)
			{
				/* TelephonyManagerの取得判定 */
				if(mTelephonyManager != null)
				{
					// 回線種別
					mStringLineType = "3G";

					// キャリア名
					mStringCareerName = mTelephonyManager.getNetworkOperatorName();
					mStringThroughput = "";
					mStringElectricFieldStrength = "";
					mStringBssid = "";
					mStringMacAddress = "";
					mStringSsid = "";
				}
			}
			else
			{
				// その他WiMaxなど
				mStringLineType = "Other";

				// キャリア名
				mStringCareerName = "";
			}
		}
		else
		{
			/* NetworkInfo取得不可(通信回線がすべて無効)の場合 */
			/* 回線種別に無効を設定 */
			mStringLineType = "Desabled";

			/*キャリア名をクリア */
			mStringCareerName = "";
		}

		if(mCalendar != null)
		{
			mStringDayTime = (
			 		/*Integer.toString(*/String.format("%02d",mCalendar.get(Calendar.YEAR)) + "/" +
					/*Integer.toString(*/String.format("%02d",mCalendar.get(Calendar.MONTH)+1) + "/" +
					/*Integer.toString(*/String.format("%02d",mCalendar.get(Calendar.DAY_OF_MONTH)) + " " +
					/*Integer.toString(*/String.format("%02d",mCalendar.get(Calendar.HOUR_OF_DAY)) + ":" +
					/*Integer.toString(*/String.format("%02d",mCalendar.get(Calendar.MINUTE)) + ":" +
					/*Integer.toString(*/String.format("%02d",mCalendar.get(Calendar.SECOND))
					);
		}
		//Log.d("WiFiQualityMeasurementSendInfoService","mStringDayTime="+mStringDayTime);
		mStringModel = Build.MODEL;
	}

	/* DEBUG ファイル書き出し処理 START */
	public void saveState()
	{
		try {
			if(mFile != null)
			{
				mFos = new FileOutputStream(mFile, true);
			}

			if(mFos != null)
			{
				OutputStreamWriter osw = new OutputStreamWriter(mFos, "UTF-8");
				if(osw != null)
				{
					BufferedWriter bw = new BufferedWriter(osw);
					if(bw != null)
					{
						mStringPingResult = mPingInfo.getResult();
						/* ファイルへ書き込む文字列の生成 */
						String str = mStringDayTime + mStringLineType + "\n" +					// 回線種別
										mStringDayTime + mStringThroughput + "\n" +				// スループット
										mStringDayTime + mStringElectricFieldStrength + "\n" +	// 電界強度
										mStringDayTime + mStringLatitude + "\n" +				// 緯度
										mStringDayTime + mStringLongitude + "\n" +				// 経度
										mStringDayTime + mStringBssid + "\n" +					// BSSID
										mStringDayTime + mStringMacAddress + "\n" +				// MacAddress
										mStringDayTime + mStringModel + "\n" +					// 端末種別
										mStringDayTime + mStringSsid + "\n" +					// SSID(利用ISP？)
										mStringDayTime + mStringCareerName + "\n" +
										mStringDayTime + mStringPingResult + "\n";

						// バッファへ書き込み
						bw.write(str);
						// ファイルへ書き込み
						bw.flush();
						// ファイルクローズ
						bw.close();
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	/* DEBUG ファイル書き出し処理 END */

	/**
	 * サーバへログを送信
	 */
	private void sendLog() {
		HttpClient hc = new DefaultHttpClient();
		// ログ保存先URL
		String url = "http://gae-for-android.appspot.com/wifi/upload";
		HttpPost post = new HttpPost(url);
		// パラメータを設定
		List<NameValuePair> params = new ArrayList<NameValuePair>();
		params.add(new BasicNameValuePair("time", mStringDayTime));
		params.add(new BasicNameValuePair("lineType", mStringLineType));
		params.add(new BasicNameValuePair("throughput", mStringThroughput));
		params.add(new BasicNameValuePair("strength", mStringElectricFieldStrength));
		params.add(new BasicNameValuePair("latitude", mStringLatitude));
		params.add(new BasicNameValuePair("longitude", mStringLongitude));
		params.add(new BasicNameValuePair("bssId", mStringBssid));
		params.add(new BasicNameValuePair("mcAddr", mStringMacAddress));
		params.add(new BasicNameValuePair("model", mStringModel));
		params.add(new BasicNameValuePair("ssId", mStringSsid));
		mStringPingResult = mPingInfo.getResult();
		params.add(new BasicNameValuePair("Ping", mStringPingResult));


		try {
			post.setEntity(new UrlEncodedFormEntity(params));

			HttpResponse res = hc.execute(post);
			int status = res.getStatusLine().getStatusCode();
			if (!(status == HttpStatus.SC_OK || status == HttpStatus.SC_CREATED)) {
				throw new RuntimeException("Request timeout");
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public void onLocationChanged(Location location) {
		// TODO 自動生成されたメソッド・スタブ

		if(location != null)
		{
			mStringLatitude = (Double.toString(location.getLatitude()));	// 緯度
			mStringLongitude = (Double.toString(location.getLongitude()));	// 経度
		}


	}

	@Override
	public void onProviderDisabled(String s) {
		// TODO 自動生成されたメソッド・スタブ

	}

	@Override
	public void onProviderEnabled(String s) {
		// TODO 自動生成されたメソッド・スタブ

	}

	@Override
	public void onStatusChanged(String s, int i, Bundle bundle) {
		// TODO 自動生成されたメソッド・スタブ

	}
}
